<?php
declare(strict_types=1);

namespace Core\Basics;
use function Hyperf\Support\env;
use Zms\Unit\Json;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use RedisException;

class BasicsRedis
{
    protected string $key;

    #[Inject]
    public Redis $redis;

    public function __construct()
    {
        $this->key = env('APP_NAME') . ':redis:';
    }


    /**
     * 设置缓存key
     * @param string $key
     * @return string
     */
    protected function setKey(string $key): string
    {
        if (str_starts_with($key, $this->key)) {
            return $key;
        }
        return $this->key . $key;
    }


    /**
     * 设置缓存键
     * @param $key
     * @param $value
     * @param null $timeout
     * @return bool
     * @throws RedisException
     */
    public function set($key, $value, $timeout = null): bool
    {
        $value = Json::encode(['value' => $value]);
        return (bool)$this->redis->set($this->setKey($key), $value, $timeout);
    }


    /**
     * 获取redis缓存
     * @param $key
     * @return mixed
     * @throws RedisException
     */
    public function get($key): mixed
    {
        $data = $this->redis->get($this->setKey($key));
        if ($data) {
            $data = Json::decode($data);
            return $data['value'] ?? null;
        }
        return null;
    }


    /**
     * 删除缓存
     * @param array|string $keys
     * @return bool
     * @throws RedisException
     */
    public function del(array|string $keys): bool
    {
        if (is_string($keys)) {
            $keys = [$keys];
        }
        $keyAll = [];
        foreach ($keys as $key) {
            $keyAll[] = $this->setKey($key);
        }
        return (bool)$this->redis->del($keyAll);
    }


    /**
     * 清空缓存
     * @return bool
     * @throws RedisException
     */
    public function clear(): bool
    {
        while (true) {
            $keys = $this->redis->scan($iterator, $this->setKey('*'), 1000);
            if (!empty($keys)) {
                $this->redis->del($keys);
            }
            if (empty($iterator)) {
                break;
            }
        }
        return true;
    }
}